package com.fulu.game.bi.controller.auth;

import cn.hutool.core.codec.Base64;
import com.fulu.game.bi.entity.vo.ExceptionCode;
import com.fulu.game.bi.service.impl.auth.config.BiSubject;
import com.fulu.game.bi.entity.po.auth.BiUser;
import com.fulu.game.bi.entity.vo.Result;
import com.fulu.game.bi.redis.enums.RedisKeyEnum;
import com.fulu.game.bi.redis.service.impl.RedisOpenServiceImpl;
import com.wf.captcha.Captcha;
import com.wf.captcha.GifCaptcha;
import com.wf.captcha.utils.CaptchaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户登录
 */
@Controller
@Slf4j
public class LoginController {

    private static final String SESSION_CAPTCHA = "bi:captcha";

    @Autowired
    private RedisOpenServiceImpl redisOpenService;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index() {
        return "index";
    }

    /**
     * 登录
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public Result login(String username,
                        String password,
                        String code,
                        HttpServletRequest request,
                        @RequestParam(value = "rememberMe", required = false, defaultValue = "false") Boolean rememberMe) {

        int times = 0;
        try {
            password = Base64.decodeStr(password);
            String timesStr = redisOpenService.get(RedisKeyEnum.BI_CAPTCHA_TIMES.generateKey(username));
            if (timesStr != null) {
                times = Integer.parseInt(timesStr);
            }
            if (times >= 3) {
            Object captcha = request.getSession().getAttribute(SESSION_CAPTCHA);
            String sessionCode = captcha == null ? null : captcha.toString();
            request.getSession().removeAttribute(SESSION_CAPTCHA);
                // 判断验证码
                if (code == null ||  !code.trim().equalsIgnoreCase(sessionCode)) {
                    log.info("用户验证不应该为空, 用户验证码code:{}, 服务器验证码sessionCode:{}", code, sessionCode);
                    return Result.error().data(ExceptionCode.CAPTCHA_WRONG.toObject());
                }
            }
            if (times >= 10) {
                return Result.error().data(ExceptionCode.TOO_MANY_TIMES.toObject());
            }

            UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
            BiSubject subject = (BiSubject) SecurityUtils.getSubject();
            subject.login(token);
            BiUser currentUser = subject.getCurrentUser();

            redisOpenService.delete(RedisKeyEnum.BI_CAPTCHA_TIMES.generateKey(username));
            return Result.success().data(currentUser).msg("登录成功!");
        } catch (AuthenticationException e) {
            log.error("shiro验证失败", e);
            times++;
            redisOpenService.set(RedisKeyEnum.BI_CAPTCHA_TIMES.generateKey(username), times + "", 30 * 60);
            if (times >= 3) {
                Map<String, Object> data = new HashMap<>();
                data.put("errcode", 4003);
                return Result.error().data(data).msg("登录失败,用户名或者密码错误");
            }
            return Result.error().msg("登录失败,用户名或者密码错误");
        } catch (Exception e) {
            log.error("登录异常", e);
            return Result.error().msg("登录异常");
        }
    }

    /**
     * 获取验证码
     */
    @RequestMapping("/captcha")
    public void captcha(HttpServletRequest request,
                        HttpServletResponse response) throws Exception {
        // 设置请求头为输出图片类型
        CaptchaUtil.setHeader(response);
        // 三个参数分别为宽、高、位数
        GifCaptcha gifCaptcha = new GifCaptcha(130, 48, 4);
        // 设置类型，纯数字、纯字母、字母数字混合
        gifCaptcha.setCharType(Captcha.TYPE_DEFAULT);
        request.getSession().setAttribute(SESSION_CAPTCHA, gifCaptcha.text());
        // 输出图片流
        gifCaptcha.out(response.getOutputStream());
    }

}